#ifndef RODEO_CORE_WINDOW_H_
#define RODEO_CORE_WINDOW_H_

#ifndef RODEO_CORE_ERROR_H_
#include "core\error.h"
#endif    //RODEO_CORE_ERROR_H_

#ifndef RODEO_GLLIBS_H_
#include "..\gllibs.h"
#endif    //RODEO_GLLIBS_H_

namespace rodeocore
{
    class Window
    {
    public:
        Window()
        :hwnd_(0),
         hrc_(0),
         hdc_(0),
         hinstance_(NULL),
         width_(0),
         height_(0),
         depth_(0),
         freq_(0),
         style_(-1),
         exstyles_(-1),
         fullscreen_(false),
         window_classname_("engine"),
         windowname_("Rodeo Game Engine")
        {
        }

        ~Window(){}

        // Initializes the Window object
        void init();

        // Loads custom cursor from specified location
        void loadCustomCursor(const char* file_path);

        // This method will add menu to the window
        // Call this method ONLY if you want some editor
        // in pure Win32
        void addMenu(HINSTANCE hinstance, LPCSTR menuName);

        // This method will process every message
        // This is equivalent to Win32 Callback function LRESULT WindowProcess;
        virtual LRESULT messageProcessor(UINT msg, WPARAM wparam, LPARAM lparam);

        // This method checks and translates all messages
        //void translateMessages();
        void loop();

        // Creates OpenGL Context for Windows
        bool createGLContext(HDC hdc);

        virtual void onMouseMove(int, int);
        virtual void onLeftButtonDown();
        virtual void onLeftButtonUp();
        virtual void onLeftButtonDoubleClick();
        virtual void onRightButtonDown();
        virtual void onRightButtonUp();
        virtual void onRightButtonDoubleClick();
        virtual void onMiddleButtonDown();
        virtual void onMiddleButtonUp();
        virtual void onScroll();
        virtual void onKeydown();
        virtual void onKeyup();
        virtual void onRender();
        virtual void onInit();
        virtual void onUpdate();
        void onCreate(HDC hdc);
        void onDestroy();
        void onClose();
        void onSize(int width, int height);
        virtual void onUpdate(float dt);
        void update();

        const int getHeight()const
        {
            return height_;
        }

        const int getWidth()const
        {
            return width_;
        }
        int getDepth()const { return depth_; }

        int getFrequency()const { return freq_; }

        HWND getWindowHandle()const { return hwnd_; }

        const HINSTANCE getHinstance()const { return hinstance_; }

        const HGLRC getHRC()const { return hrc_; }

        const HDC getDeviceContext()const { return hdc_; }

        const char* const getWindowClassName(){ return window_classname_; }

        const char* const getWindowName(){ return windowname_; }

        MSG getMessage() const
        {
            return msg_;
        }

        RECT getRect() const
        {
            return rect_;
        }

        void setWindowWidth(int width) { width_ = width; }

        void setWindowHeight(int height) { height_ = height; }

        void setDepth(int depth) { depth_ = depth; }

        void setFrequency(int freq) { freq_ = freq; }

        bool getFullscreen() const
        {
            return fullscreen_;
        }

        void setFullscreen(bool fullscreen)
        {
            fullscreen_ = fullscreen;
        }

        WNDCLASSEX getWindowClass()
        {
            return wnd_;
        }

    //private:
        // Fills out Window Class (WNDCLASSEX)
        // Parameter HINSTANCE - GetModuleHandle(NULL)
        // Parameter const char* - getWindowClassName()
        bool createWindowClass(HINSTANCE hinstance, const char* classname);

        // This method calls CreateWindowEx(), applies styles, 
        //    and checks if window is in fullscreen mode
        HWND window(const char* classname, const char* windowname, HINSTANCE hinstance, int w, int h);

        // This method calls Win32 RegisterClassEx()
        bool registerClass();

        // This method calls Win32 ShowWindow(), UpdateWindow(), SetFocus();
        bool show();

        void toggleFullScreen();

        void setupPixelFormat(HDC hdc);

        bool startWiggle(HDC hdc);

        bool stopWiggle();

        bool setRect();

        bool setRect(int left, int top, int right, int bottom);
        int shutdown();

        void setWindow(int width, int height, int depth, int frequency);

        bool checkFullscreen();

        bool changeResolution(int w, int h);

        void setHRC(HGLRC hrc) { hrc_ = hrc; }


        void setClassName(const char* cn){ window_classname_ = cn; }

        void setWindowName(const char* wn){ windowname_ = wn; }

//==== MEMBERS ====//
        WNDCLASSEX wnd_;
        HWND hwnd_;
        HGLRC hrc_;
        HDC hdc_;
        HINSTANCE hinstance_;
        MSG msg_;
        RECT rect_;

        int width_;
        int height_;
        int depth_;
        int freq_;

        // WS_BORDER | WS_OVERLAPPEDWINDOW | WS_VISIBLE
        int style_;

        // WS_EX_APPWINDOW | WS_EX_WINDOWEDGE
        int exstyles_;

        bool fullscreen_;

        const char* window_classname_;
        const char* windowname_;
    };
}    // end of rodeocore namespace

#endif    //RODEO_CORE_WINDOW_H_